package com.gitee.wsl.func

import com.gitee.wsl.ext.K
import kotlinx.coroutines.CoroutineScope


typealias RunWithResultFun<T> = () -> T
typealias SuspendRunWithResultFun<T> = suspend () -> T

typealias RunAbleFun = RunWithResultFun<Unit>
typealias SuspendRunAbleFun = SuspendRunWithResultFun<Unit>


typealias CallAbleFun<A,R> = (A) -> R
typealias CallSelfFun<A,R> = A.() -> R
typealias SuspendCallAbleFun<A,R> = suspend (A) -> R
typealias SuspendCallSelfFun<A,R> = suspend A.() -> R


typealias CallAbleFun2N<A,R> = (A, A) -> R
typealias SuspendCallAbleFun2N<A,R> = suspend (A, A) -> R

typealias CallAbleFun3N<A,R> = (A, A, A) -> R
typealias SuspendCallAbleFun3N<A,R> = suspend (A, A, A) -> R

typealias BiCallAbleFun<A,B,R> = (A, B) -> R
typealias BiCallSelfFun<A,B,R> = A.(B) -> R
typealias SuspendBiCallAbleFun<A,B,R> = suspend (A, B) -> R
typealias SuspendBiCallSelfFun<A,B,R> = suspend A.(B)  -> R

typealias FailureFun = CallAbleFun<Throwable,Unit>


typealias CoroutineCallSelfFun<T> = SuspendCallSelfFun<CoroutineScope,T>


//fun test(){
//    val a: CallAbleFun<Int,Int> = {a-> a}
//
//    val aU: CallSelfFun<Int,Int> = { this + 16 }
//
//    val b = aU(25) + a(20)
//
//    fun test(wq:CallAbleFun<Int,Int>) = wq(25)
//
//    test(a)
//
//    test(aU)
//}


/**
 * Executes a collection of blocks, capturing any exceptions thrown.
 *
 * This function iterates over the given [blocks] and executes each one.
 * If an exception is thrown,
 * it is either stored as the initial exception or added as a suppressed exception to the initial one.
 *
 * @param blocks A collection of functions to be executed.
 * @return The first exception that was thrown, with any subsequent exceptions added as suppressed exceptions.
 * Returns `null` if no exceptions were thrown.
 */
 fun K.tryEverything(blocks: Iterable<RunAbleFun>): Exception? {
    var suppress: Exception? = null
    blocks.forEach {
        try {
            it()
        } catch (e: Exception) {
            if (suppress == null) {
                suppress = e
            } else {
                suppress.addSuppressed(e)
            }
        }
    }
    return suppress
}


/**
 * Executes a vararg array of blocks, capturing any exceptions thrown.
 *
 * This function converts the vararg [blocks] to a list and delegates to [tryEverything] with the list of blocks.
 *
 * @param blocks A vararg array of functions to be executed.
 * @return The first exception that was thrown, with any subsequent exceptions added as suppressed exceptions.
 * Returns `null` if no exceptions were thrown.
 */
fun K.tryEverything(vararg blocks: () -> Unit): Exception? = tryEverything(blocks.toList())